home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d7 / jmodm308.arc / JMODEM_C.DOC < prev    next >
Text File  |  1991-01-02  |  45KB  |  1,181 lines

  1.  
  2.                                   J M O D E M
  3.                          *  The Microsoft C Version  *
  4.                                 January 2, 1991
  5.                                Richard B. Johnson
  6.                               405 Broughton Drive
  7.                           Beverly Massachusetts 01915
  8.                                BBS (508) 922-3166
  9.  
  10.           Introduction.
  11.  
  12.           JMODEM was first introduced about two years ago. It has en-
  13.           joyed a steady increase in popularity around the world. It
  14.           has even been explained in some detail in John Dvorak's book
  15.           on PC communications; Dvorak's Guide to PC Telecommunica-
  16.           tions, 1990, Osborne-McGraw-Hill, 2600 Tenth Street,
  17.           Berkeley, CA.
  18.  
  19.           JMODEM was first written in assembly language. Since this
  20.           language is hard to read and use, it has been difficult for
  21.           communications program developers to incorporate it into
  22.           their programs directly. Instead it must be executed as an
  23.           external protocol. Now JMODEM has been written in the C
  24.           Language. C has become the de-facto standard for portable
  25.           code development even though there isn't presently any code
  26.           that is truly portable across many different machines. The
  27.           writing of JMODEM in C will make it easier for software de-
  28.           velopers throughout the world to use this very useful pro-
  29.           tocol.
  30.  
  31.           You can use this new version of JMODEM just as the older
  32.           versions written in assembly. It has a new color sign-on
  33.           screen and status-block windows that overlap. Although the
  34.           new JMODEM.EXE code is larger than the assembly-language
  35.           version, JMODEM.COM, the program still executes very fast
  36.           because much effort has been taken to streamline the C code.
  37.           JMODEM.COM required 64 k of RAM (one segment) to execute
  38.           properly. JMODEM.EXE requires 79 k to allow the screens to
  39.           be written properly, and 66 k of free RAM to execute without
  40.           aborting although the previous screen content will be lost.
  41.           Like all versions of JMODEM, this version is 100% compatible
  42.           with all previous version including Beta version 1.00. From
  43.           it's inception, the essential structure of JMODEM has never
  44.           been changed.
  45.  
  46.           How to install JMODEM.
  47.  
  48.           JMODEM executes best from a batch file as an external pro-
  49.           tocol for any of the communications programs that have ex-
  50.           ternal-protocol capability. A typical communications program
  51.           is TELIX.
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.                                      - 1 -
  60.                                                JMODEM, the C Version
  61.  
  62.  
  63.  
  64.           Here is a batch file used with TELIX for uploads:
  65.  
  66.           @ECHO OFF
  67.           Rem * JMODEM TELIX Upload batch file.
  68.           C:\TELIX\JMODEM S1 %3
  69.           Rem           | ||  |_________ file name (passed by TELIX)
  70.           Rem           | ||____________ COM port (1 - 4)
  71.           Rem           | |_____________ Send
  72.           Rem           |_______________ Path and name of JMODEM
  73.  
  74.  
  75.           This is a batch file used with TELIX for downloads:
  76.  
  77.           @ECHO OFF
  78.           Rem * JMODEM TELIX Download batch file.
  79.           C:\TELIX\JMODEM R1 %3
  80.           Rem           | ||  |_________ file name (passed by TELIX)
  81.           Rem           | ||____________ COM port (1 - 4)
  82.           Rem           | |_____________ Receive
  83.           Rem           |_______________ Path and name of JMODEM
  84.  
  85.  
  86.           This is a batch file used for PCPLUS (PROCOMM) uploads:
  87.  
  88.           @ECHO OFF
  89.           Rem * JMODEM PCPLUS Upload batch file.
  90.           C:\TELIX\JMODEM S1 %1
  91.           Rem           | ||  |_________ file name (passed by PCPLUS)
  92.           Rem           | ||____________ COM port (1 - 4)
  93.           Rem           | |_____________ Send
  94.           Rem           |_______________ Path and name of JMODEM
  95.  
  96.  
  97.           This is a batch file for PCPLUS (PROCOMM) ownloads:
  98.  
  99.           @ECHO OFF
  100.           Rem * JMODEM PCPLUS Download batch file.
  101.           C:\TELIX\JMODEM R1 %1
  102.           Rem           | ||  |_________ file name (passed by PCPLUS)
  103.           Rem           | ||____________ COM port (1 - 4)
  104.           Rem           | |_____________ Receive
  105.           Rem           |_______________ Path and name of JMODEM
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.                                      - 2 -
  119.                                                JMODEM, the C Version
  120.  
  121.  
  122.           If I wished to receive in the "batch" mode, I could make a
  123.           file like this. Notice that some communications programs do
  124.           not allow multiple file names. Note that the comments "!"
  125.           are NOT ALLOWED in a DOS batch file.
  126.  
  127.                         :DO_LOOP                   ! Return here
  128.                         IF "%3" == "" GOTO DONE    ! More parameters?
  129.                         C:\TELIX\JMODEM R1 %3      ! Execute JMODEM
  130.                         IF ERRORLEVEL 1 GOTO DONE  ! Abort on error
  131.                         SHIFT                      ! %4 becomes %3
  132.                         GOTO DO_LOOP               ! Continue
  133.                         :DONE                      ! Exit batch file
  134.  
  135.           If you do not know what "%" parameters are used to pass the
  136.           file name, all you have to do is make a "dummy" batch file
  137.           that contains the following:
  138.  
  139.                         @ECHO OFF
  140.                         ECHO %1
  141.                         ECHO %2
  142.                         ECHO %3
  143.                         ECHO %4
  144.                         ECHO %5
  145.                         PAUSE
  146.  
  147.           When this is executed, you will see something like this:
  148.  
  149.                 1200
  150.                 1
  151.                 FILENAME.TYP
  152.                 ECHO is off
  153.                 ECHO is off
  154.                 Strike a key when ready . . .
  155.  
  156.           The first line contains "1200" which is the baud rate. This
  157.           means that the %1 parameter contains the baud rate.
  158.  
  159.           The second line contains "1" which is the communications
  160.           adapter port being used. This means that the port is being
  161.           passed as the %2 parameter.
  162.  
  163.           The third line contains "FILENAME.TYP" which is the file
  164.           name. This means that the file name is being passed as the
  165.           %3 parameter.
  166.  
  167.           The fourth and fifth lines contain nothing to echo so DOS
  168.           replies the current state of the echo function which is
  169.           "off".
  170.  
  171.           PCPLUS handles the file name passing a little bit different.
  172.           If I execute the same "dummy" batch file from the PCPLUS
  173.           directory, the response is:
  174.  
  175.  
  176.  
  177.                                      - 3 -
  178.                                                JMODEM, the C Version
  179.  
  180.  
  181.  
  182.                 FILENAME.TYP
  183.                 ECHO is off
  184.                 ECHO is off
  185.                 ECHO is off
  186.                 ECHO is off
  187.                 Strike a key when ready . . .
  188.  
  189.           This shows us that PCPLUS passes the file name as the first
  190.           parameter and there are no other parameters. However, If I
  191.           put more parameters on the command line within PCPLUS, they
  192.           will get sent to the batch file. The response is:
  193.  
  194.                 FILENAME.001
  195.                 FILENAME.002
  196.                 FILENAME.003
  197.                 FILENAME.
  198.                 ECHO is off
  199.                 Strike a key when ready . . .
  200.  
  201.           Therefore PCPLUS allows up to four file names to be passed
  202.           providing there's room on the command line.
  203.  
  204.           Notice that these two communications programs check the
  205.           default directory for the external protocol batch file
  206.           FIRST! Therefore you must make certain that there are no
  207.           other similarly-named batch files in the current directory
  208.           or within the current path. Failure to do so will cause the
  209.           improper execution of the wrong batch file. Lets say that
  210.           the path was "C:\DOS;C:\TOOLS;C:\PCPLUS;C:\TELIX;C:\QMODEM".
  211.           If you named all your JMODEM external protocol batch files
  212.           with the same name, and you were attempting to use an ex-
  213.           ternal file transfer protocol from QMODEM, the batch file
  214.           designed to operate with PCPLUS would be the first one
  215.           "found" and executed since the search-path will search the
  216.           \PCPLUS directory before the \QMODEM directory. You prevent
  217.           the execution of the incorrect batch file by calling them
  218.           slightly different names.
  219.  
  220.           When setting up external protocols, remember to configure
  221.           the communications program so that it prompts you for the
  222.           file names. Unlike some protocols, JMODEM does not transfer
  223.           the file name. You can use any file name that you wish. You
  224.           must pass the file name to JMODEM since it must know the
  225.           name of the file being transmitted or received. There are no
  226.           defaults.
  227.  
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.                                      - 4 -
  237.                                                JMODEM, the C Version
  238.  
  239.  
  240.                             Setting up a BBS System
  241.                         External File-Transfer Protocol.
  242.  
  243.  
  244.           If you are running a WILDCAT! bulletin board, the external
  245.           protocol files can be set up like this:
  246.  
  247.                         (JUP.BAT)
  248.                         CD D:\WILDCAT\PROTOCOL
  249.                         IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
  250.                         JMODEM R1 %3
  251.                         IF ERRORLEVEL 1 GOTO END
  252.                         COPY %3 %4
  253.                         :END
  254.                         DEL %3
  255.  
  256.                         (JDOWN.BAT)
  257.                         CD D:\WILDCAT\PROTOCOL
  258.                         IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
  259.                         JMODEM S1 %3
  260.                         IF ERRORLEVEL 1 GOTO BAD
  261.                         GOTO END
  262.                         :BAD
  263.                         COPY ALL.OK TRANSFER.BAD
  264.                         :END
  265.  
  266.           There are many variations available. Since WILDCAT! supports
  267.           batch-mode downloading, you could set up the batch file like
  268.           this:
  269.  
  270.                         (JDOWN.BAT)
  271.                         CD D:\WILDCAT\PROTOCOL
  272.                         IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
  273.                         :DO_LOOP
  274.                         IF "%3" == "" GOTO END
  275.                         JMODEM S1 %3
  276.                         IF ERRORLEVEL 1 GOTO BAD
  277.                         SHIFT
  278.                         GOTO DO_LOOP
  279.                         :BAD
  280.                         COPY ALL.OK TRANSFER.BAD
  281.                         :END
  282.  
  283.           WILDCAT! checks the \PROTOCOL directory to see if the file
  284.           TRANSFER.BAD has been created. If it exists, it announces
  285.           that the file transfer has failed. It also announces "Error
  286.           with external protocol .. ". It does this when, in fact,
  287.           WILDCAT!  has made an error itself. In many cases WILDCAT!
  288.           will "find" the file TRANSFER.BAD when it DOES NOT EXIST! In
  289.           spite of this bug, WILDCAT! is one of the most reliable BBS
  290.           systems supporting external protocols.
  291.  
  292.  
  293.  
  294.  
  295.                                      - 5 -
  296.                                                JMODEM, the C Version
  297.  
  298.  
  299.  
  300.           When setting up batch files remember that there is also a
  301.           bug in all DOS versions. The "IF ERRORLEVEL " statement does
  302.           NOT test the actual value of ERRORLEVEL! Instead it checks
  303.           to see if the returned value is EQUAL or GREATER than the
  304.           tested value. If you were to put the statement:
  305.  
  306.                         IF ERRORLEVEL 0 GOTO GOOD
  307.  
  308.           .... in a batch file, the execution would ALWAYS branch to
  309.           label "GOOD" regardless of the actual ERRORLEVEL returned!
  310.  
  311.           JMODEM does not require any information about handshaking.
  312.           It will look at the modem port and figure out for itself
  313.           what to do.
  314.  
  315.           In the event that the modem carrier is lost, JMODEM will
  316.           abort. Since JMODEM only checks the modem port occasionally,
  317.           it may take several seconds to abort when the carrier is
  318.           lost. It is impossible for a user to get at the DOS level
  319.           through JMODEM. Do NOT use the CTTY command in the external
  320.           protocol batch files. JMODEM returns ERRORLEVEL 1 if there
  321.           was any error in transmission or reception. It returns
  322.           ERRORLEVEL 0 (no error) otherwise. It does not delete files
  323.           that have been partially received although it properly clos-
  324.           es them. The system operator can arrange the batch files to
  325.           delete them if required.
  326.  
  327.           When JMODEM attempts to create a file that already exists it
  328.           can't ask the user if the old one should be deleted since
  329.           the user is probably not in a terminal program at the time.
  330.           Therefore, JMODEM renames the other file to <filename.OLD>
  331.           and creates the new file. In the event that <filaname.OLD>
  332.           exists, it is deleted before the rename operation occurs.
  333.  
  334.           If you don't know what parameters are being sent to external
  335.           protocols, you can make a dummy batch file to check them
  336.           using the DOS's echo command just as explained in the user
  337.           interface previous to this "BBS" section. You can't see the
  338.           parameters being echoed from a remote terminal. You must be
  339.           present at the BBS board terminal to test those parameters
  340.           unless you modify the dummy command file like this:
  341.  
  342.                         @ECHO OFF
  343.                         ECHO %1>COM1
  344.                         ECHO %2>COM1
  345.                         ECHO %3>COM1
  346.                         ECHO %4>COM1
  347.                         ECHO %5>COM1
  348.  
  349.           If you find that your system passes the file name as %3,
  350.           your "upload" (receive) batch file would contain this:
  351.  
  352.  
  353.  
  354.                                      - 6 -
  355.                                                JMODEM, the C Version
  356.  
  357.  
  358.  
  359.                         JMODEM R1 %3
  360.  
  361.           Your "download" (send) batch file would contain this:
  362.  
  363.                         JMODEM S1 %3
  364.  
  365.           In these examples, it is assumed that you are using
  366.           communications adapter port "1".
  367.  
  368.           You can chop this text out with an editor and create your
  369.           batch files quickly and correctly. PCPLUS passes the file-
  370.           name as the %1 parameter and TELIX uses the %3 parameter.
  371.           JMODEM does not need to know anything else about your system
  372.           to operate. It does not even need to know the baud-rate or
  373.           other communications parameters. All it needs to know about
  374.           is the file name and the communications adapter port to use.
  375.  
  376.           JMODEM doesn't care if you are using a 19,200 baud modem
  377.           with the DTE locked at high-speed or a 300 baud modem on a
  378.           lamp-cord. It is very smart about communications and handles
  379.           lost carriers (hangup) and flow-control in a very simple way
  380.           which will be explained in detail later.
  381.  
  382.           If you only want to try JMODEM without having to install it,
  383.           you need only to activate the JMODEM protocol on a BBS sys-
  384.           tem, then "shell to DOS" and execute it manually from the
  385.           DOS prompt. You will be pleasantly surprised at how rapidly
  386.           it can transfer a file and how well it executes over net-
  387.           works.
  388.  
  389.           How JMODEM works.
  390.  
  391.           JMODEM uses variable-length records called blocks. These
  392.           blocks start with 512 data-bytes and increase in length to a
  393.           maximum of 8192 bytes per block. There is a 6-byte overhead
  394.           associated with each block so the percentage of overhead
  395.           starts at a fairly high 0.1 percent and decreases to a very
  396.           low 0.07 percent as the transmission progresses. The block
  397.           length will increase in 512-byte increments as long as there
  398.           are no errors requiring retransmission. Should an error
  399.           occur, the block-size is cut in half. This continues until
  400.           the block-size is as short as 64 bytes.
  401.  
  402.           The blocks may actually be of any length but never exceed
  403.           the maximum allowed. An attempt is made to reduce the amount
  404.           of data that needs to be transmitted by compressing each
  405.           block before transmission. Since much data is already com-
  406.           pressed, being from ".ZIP" files and such, it is possible
  407.           that "compression" may actually cause an increase in block-
  408.           length. JMODEM will send a compressed block only if it is
  409.           shorter than the non-compressed block.
  410.  
  411.  
  412.  
  413.                                      - 7 -
  414.                                                JMODEM, the C Version
  415.  
  416.  
  417.  
  418.           Since it takes time to compress and expand data, only the
  419.           simplest and quickest compression method is used. It is very
  420.           effective with ".EXE" files that contain large blocks of
  421.           binary nulls and most text files but it is not very effec-
  422.           tive with highly compressed archive files. The compression
  423.           method is called "run-length-limited" or more explicitly
  424.           "how many of what kind". Basically, the block is searched
  425.           for groups if similar characters. If many similar characters
  426.           are found, compression consists of sending a sentinel byte
  427.           of hexadecimal BB, followed by a two-byte amount, and this
  428.           followed by the byte to be repeated.
  429.  
  430.           In the following example we have a string of spaces (20
  431.           hex).
  432.  
  433.           Before compression:
  434.                                ( 18 bytes )
  435.             20 20 20 20 20 20 20 20 20 20 20 34 37 87 EF FF 3A 23
  436.  
  437.  
  438.           After compression:
  439.                                ( 11 bytes )
  440.             BB 0B 00 20 34 37 87 EF FF 3A 23
  441.  
  442.           The blocks could actually get longer because the sentinel
  443.           byte could be present in the data:
  444.  
  445.           Before compression:
  446.                                ( 9 bytes )
  447.             BB 00 BB AF EF BB 00 AE EF
  448.  
  449.  
  450.           After compression:
  451.                                ( 16 bytes )
  452.             BB 01 00 BB 00 BB 01 00 BB AF BB 01 00 BB AE EF
  453.  
  454.           As soon as the encoded length exceeds the data block length,
  455.           compression is abandoned and the non-compressed block is
  456.           sent. JMODEM sends a byte that tells the receiver if the
  457.           data is compressed or not. This same byte tells the receiver
  458.           when the end-of-file has occurred so JMODEM is able to
  459.           preserve exact file-length.
  460.  
  461.                                The JMODEM block.
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.  
  472.                                      - 8 -
  473.                                                JMODEM, the C Version
  474.  
  475.  
  476.  
  477.           The JMODEM block looks like this:
  478.  
  479.            |< --------- First byte sent / received
  480.           20 00 01 01 .. .. .. .. .. AE 01
  481.            |  |  |  |        |        |  |___ CRC (high byte)
  482.            |  |  |  |        |        |______ CRC (low byte)
  483.            |  |  |  |        |_______________ data bytes
  484.            |  |  |  |________________________ type of block
  485.            |  |  |___________________________ block number
  486.            |  |______________________________ block length (high byte)
  487.            |_________________________________ block length (low byte)
  488.  
  489.  
  490.           The Block length:
  491.  
  492.           The block length is a WORD (16 bits). This allows the blocks
  493.           to be 65,535 bytes long although in practice the length is
  494.           not allowed to exceed 8192 bytes (plus overhead). The block-
  495.           length is the length of the entire JMODEM block, not just
  496.           the data-bytes.
  497.  
  498.           The Block number:
  499.  
  500.           The block number is a BYTE. It starts at 1 and becomes zero
  501.           again after block 255. It is used to make certain that all
  502.           receiption errors are detected.
  503.  
  504.           The Block type:
  505.  
  506.           This BYTE is bit-mapped to tell the receiver what kind of
  507.           block has been sent. Presently there are three kinds of
  508.           blocks:
  509.  
  510.                 00000000B       Hex 00  ( Normal data )
  511.                 00000001B       Hex 01  ( Compressed data )
  512.                 00000010B       Hex 02  ( End of file )
  513.  
  514.           The CRC:
  515.  
  516.           The CRC is a WORD (16 bits). It is not a "standard" type of
  517.           CRC because, unless done with hardware, a standard 16-bit
  518.           polynomial would take several seconds to calculate for a
  519.           long block. Instead it uses a rapid rotate and sum algorithm
  520.           that is probably just as effective as the more "standard"
  521.           polynomials.
  522.  
  523.           The CRC is generated using this polynomial:
  524.  
  525.           X =  X + X^(2(n-mod 7)).......  Where n = t(n-1)
  526.                                          And t = string length
  527.  
  528.  
  529.  
  530.  
  531.                                      - 9 -
  532.                                                JMODEM, the C Version
  533.  
  534.  
  535.  
  536.           It has the advantage of simplicity in assembly-language
  537.           programming and will detect errors with a probability of
  538.           about  one undetected error in 2^132 (which is a very large
  539.           number). It does not correct errors so its not important to
  540.           use some "standard" function to generate the CRC.
  541.  
  542.           The C code shows how easy it is to create and check this
  543.           kind of CRC.
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.  
  590.                                      - 10 -
  591.                                                JMODEM, the C Version
  592.  
  593.  
  594.                            The JMODEM Communications
  595.                                 Hardware Control
  596.  
  597.           When JMODEM is first loaded for execution it checks the
  598.           state of the modem-control leads. If there is no modem
  599.           carrier detected, it assumes that you have connected two PCs
  600.           together without a modem and will not bother to check for a
  601.           dropped carrier during execution.
  602.  
  603.           Since JMODEM must exercise flow-control so it can be used
  604.           with high-speed modems with fixed baud rates, it also as-
  605.           sumes that at the time at which it is first executed, the
  606.           modem will be requesting data because there will have been
  607.           very little I/O over the previous few seconds. JMODEM stores
  608.           the state of RTS/CTS and DTR/DSR and uses this as a refer-
  609.           ence. When transmitting data, should JMODEM find that the
  610.           state of these modem-control leads has changed, it waits
  611.           until the modem-control leads have reverted back to the
  612.           initial state before sending any more data. This allows ANY
  613.           modem to exercise flow-control with JMODEM, even those that
  614.           use "pin 4" instead of "pin 20". When JMODEM is waiting, it
  615.           checks to verify that the modem carrier has not been drop-
  616.           ped. If the carrier is dropped, or if the user aborts,
  617.           JMODEM will exit, setting a DOS ERRORLEVEL code.
  618.  
  619.           You can abort JMODEM at any time by hitting Ctrl-Break or
  620.           Ctrl-C. It will take several seconds for JMODEM to abort
  621.           because it does not continually check these keys. Unlike
  622.           previous versions, JMODEM erases the files from aborted
  623.           downloads. Also, JMODEM will abort if it is unable to rename
  624.           a file in the following example.
  625.  
  626.           Suppose you wish to download a file called VIRUS.EXE. Sup-
  627.           pose also that VIRUS.EXE already exists. Instead of over-
  628.           writing your previous version of VIRUS.EXE, JMODEM has al-
  629.           ways been nice and renamed it to VIRUS.OLD before creating a
  630.           new file. With previous versions of JMODEM, if VIRUS.OLD
  631.           already existed, JMODEM would have deleted it before renam-
  632.           ing the present file to ".OLD". This no longer is done.
  633.           JMODEM never deletes ANYTHING anymore except it's own abort-
  634.           ed download. This should reduce the number of threats I have
  635.           received!
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.                                      - 11 -
  650.                                                JMODEM, the C Version
  651.  
  652.  
  653.                                The C programmer's
  654.                                 Guide to JMODEM
  655.  
  656.           Included within this package should be the following files:
  657.           JMODEM         This is a Microsoft MAKE file for JMODEM.EXE.
  658.           JMODEMTC       Borland's Turbo C MAKE file for JMODEM.EXE.
  659.           JMODEM    EXE  The executable file
  660.           JMODEMTC  RSP  Link response file for Borland's Turbo C
  661.           JMODEM_A  C    Contains the _main() routine entry point.
  662.           JMODEM_B  C    Allocates memory, parses input strings.
  663.           JMODEM_C  C    All of the file I/O is in this file.
  664.           JMODEM_D  C    Data compression/expansion, CRC calculation
  665.           JMODEM_E  C    Communications I/O interrupt service, etc.
  666.           JMODEM_F  C    Screen I/O (windows, etc)
  667.           JMODEM    H    Contains JMODEM globals and data structures.
  668.           SCREEN    H    Screen definitions, prototypes, structures
  669.           UART      H    Definitions for the 8250 UART
  670.           TEST      C    This tests compression /expansion, disk I/O.
  671.           TEST           This is the Microsoft MAKE file for TEST.EXE
  672.           TESTTC         Borland's Turbo C MAKE file for TEST.EXE
  673.           SHOW      C    Source for verifying execution in a DOS shell
  674.           SHOW           Microsoft MAKE file for SHOW.EXE
  675.           SHOWTC         Borland's Turbo C MAKE file for SHOW.EXE
  676.           SHOW      EXE  Executes JMODEM from a DOS shell.
  677.           TEST      C    Tests JMODEM data-compression and file I/O.
  678.           TEST           Microsoft MAKE file for TEST.EXE
  679.           TESTTC         Borland's Turbo C MAKE file for TEST.EXE
  680.           TEST      EXE  Executable to test file I/O and compression
  681.  
  682.           If you have MicroSoft 'C' version 5.0 or later, and if your
  683.           environment and paths are properly set up, you should be
  684.           able to type:
  685.  
  686.                 MAKE JMODEM
  687.                 ... and a brand new version of JMODEM will be created.
  688.  
  689.           If you use Borland's Turbo C, you can use the "TC" make
  690.           files to do the same.
  691.  
  692.           Brad Smith from Jacksonville North Carolina created the MAKE
  693.           files for Turbo C and modified the source-code to accommo-
  694.           date the different libraries used in Turbo C. His revisions
  695.           will be present in all subsequent versions of JMODEM to
  696.           assure compatibility with Borland's Turbo C.
  697.  
  698.           Brad is a Turbo C guru and runs a BBS system in
  699.           Jacksonville.
  700.  
  701.                 Brad Smith
  702.                 141 Riggs Street
  703.                 Jacksonville, North Carolina 28540
  704.                 BBS (919) 455-5972 12/24/9600+ 24 hrs
  705.  
  706.  
  707.  
  708.                                      - 12 -
  709.                                                JMODEM, the C Version
  710.  
  711.  
  712.  
  713.           With this release, there seems to be a Null-Pointer
  714.           assignment error when using Borland's Small Model in TCC
  715.           Version 1.5. This is a compiler bug, or more specifically a
  716.           bug in the C0.ASM code provided with the compiler that you
  717.           can fix.
  718.  
  719.           If you are a Turbo C programmer, don't use the small model
  720.           when creating JMODEM.EXE unless you repair the C0.ASM file
  721.           and create a new C0S.OBJ file using the MAKE-C0.BAT file
  722.           that is provided with the compiler.
  723.  
  724.  
  725.           To fix the null-pointer problem in Turbo-C find the
  726.           following code-fragment in \LIB\C0.ASM provided with your
  727.           compiler:
  728.  
  729.  
  730.           IFNDEF        __HUGE__
  731.  
  732.           ;     Reset un-initialized datas
  733.  
  734.                         xor     ax, ax
  735.                         mov     es, cs:DGROUP@@
  736.                         mov     di, offset DGROUP: bdata@
  737.                         mov     cx, offset DGROUP: edata@
  738.                         sub     cx, di
  739.                 rep     stosb
  740.           ENDIF
  741.  
  742.           Add the following code:
  743.  
  744.                 push    ds
  745.                 mov     ax,DGROUP
  746.                 mov     ds,ax
  747.                 mov     word ptr ds:[0],0
  748.                 pop     ds
  749.  
  750.  
  751.           Now find this next code-fragment:
  752.  
  753.                         xor     ax, ax
  754.                         mov     si, ax
  755.                         mov     cx, lgth_CopyRight
  756.                         cld
  757.           ComputeChecksum label near
  758.                         add     al, [si]
  759.                         adc     ah, 0
  760.                         inc     si
  761.                         loop    ComputeChecksum
  762.                         sub     ax, CheckSum
  763.  
  764.  
  765.  
  766.  
  767.                                      - 13 -
  768.                                                JMODEM, the C Version
  769.  
  770.  
  771.                         jz      ExitToDOS
  772.                         mov     cx, lgth_NullCheck
  773.                         mov     dx, offset DGROUP: NullCheck
  774.                         call    ErrorDisplay
  775.  
  776.           Modify the code so it looks like this:
  777.  
  778.           ;             xor     ax, ax
  779.           ;             mov     si, ax
  780.           ;             mov     cx, lgth_CopyRight
  781.           ;             cld
  782.           ;ComputeChecksum label        near
  783.           ;             add     al, [si]
  784.           ;             adc     ah, 0
  785.           ;             inc     si
  786.           ;             loop    ComputeChecksum
  787.           ;             sub     ax, CheckSum
  788.  
  789.                 push    ds
  790.                 mov     ax,DGROUP
  791.                 mov     ds,ax
  792.                 cmp     word ptr ds:[0],0
  793.                 pop     ds
  794.  
  795.                         jz      ExitToDOS
  796.                         mov     cx, lgth_NullCheck
  797.                         mov     dx, offset DGROUP: NullCheck
  798.                         call    ErrorDisplay
  799.  
  800.  
  801.           After to have done this, execute MAKE-C0.BAT for the small
  802.           model library from the DOS prompt:
  803.  
  804.           F:\TURBOC\LIB> MAKE-C0 SMALL
  805.  
  806.           This will create a new small-model startup object file.
  807.  
  808.           Just as in the MASM language files, the source code is
  809.           strongly-typed. All function prototypes are declared and no
  810.           defaults are used. You can compile at warning-level 3, the
  811.           most stringent level available with Microsoft compilers, and
  812.           you will get no warning errors at all. The default warning
  813.           level with Borland's compiler is even more stringent. You
  814.           will get a single warning error when compiling TEST.C as the
  815.           compiler discovers that dummy parameter "one" in the dummy
  816.           screen routine isn't used at all. It has been my experience
  817.           that if you get any warnings (in real code), they MUST be
  818.           fixed or they will bite you later on.
  819.  
  820.           Example:
  821.                         *memory++ = foo;
  822.  
  823.  
  824.  
  825.  
  826.                                      - 14 -
  827.                                                JMODEM, the C Version
  828.  
  829.  
  830.                 ... will bump the memory pointer after you put foo
  831.                 into memory. Suppose you get to the end of the block
  832.                 and wish to index backwards.
  833.  
  834.                 Do you use ...
  835.                         --*memory = foo;
  836.                 ...?
  837.  
  838.                 You do NOT!! You must use:
  839.  
  840.                         *(--memory) = foo;
  841.  
  842.           Little things like this (this is a BIG, BIG bug), could
  843.           cause code to work <sometimes> and keep you awake nights.
  844.           JMODEM has been carefully written to prevent bugs like this.
  845.           It is impossible to be sure that there are no bugs in even
  846.           simple code so be careful if you modify the source.
  847.  
  848.           You may modify JMODEM for your own use, but  P L E A S E  do
  849.           NOT distribute the modified version on BBS systems because I
  850.           do not wish to support 222,500 versions of JMODEM! If you
  851.           find a bug, or wish to improve or add something that will
  852.           increase the value of JMODEM without making it incompatible
  853.           with previous versions, please upload your improvements to
  854.           my BBS system and I may include the revisions (with your
  855.           name attached) in an upcoming version. Note that there are 6
  856.           "type" bits available in the JMODEM control-byte that could
  857.           be used to tell the receiver that another file is coming,
  858.           etc., (for batch). Things like this could be added without
  859.           destroying compatibility with previous versions.
  860.  
  861.           MicroSoft C seems to have several bugs one of which affects
  862.           files that are very long (over 256k). My first attempts to
  863.           use C files under MicroSoft for JMODEM used the stream-I/O
  864.           (FILE *) type of files. This resulted in corruption of long
  865.           files. Therefore I implemented the UNIX/DOS type of file-I/O
  866.           that uses handles rather than file-control blocks. These
  867.           work rather well.
  868.  
  869.           Starting with Version V3.06, The JMODEM distribution file
  870.           will no longer contain the old JMODEM.ASM source. This is to
  871.           reduce the download time. The C version is now mature enough
  872.           so that there is little or no difference between the per-
  873.           formance of JMODEM.COM, the assembly version, and
  874.           JMODEM.EXE, the C version. The original C version was about
  875.           25 k in length. It is now only about 12.
  876.  
  877.           Floating point:
  878.  
  879.           Originally no floating-point libraries were used. The de-
  880.           fault is still not to use any because they result in doubl-
  881.  
  882.  
  883.  
  884.  
  885.                                      - 15 -
  886.                                                JMODEM, the C Version
  887.  
  888.  
  889.           ing the size of the code. Some persons have complained that
  890.           the speed (cps) indication is not very accurate. This is
  891.           true because of the granularity of the time returned from
  892.           DOS (one second). If you add /DFTIME to the command-line
  893.           used to compile JMODEM_A.C in the "MAKE" file, the compiler
  894.           will use floating-point routines for the speed calculation.
  895.           The resulting JMODEM.EXE will be about 35k in length,
  896.           though, so this is a trade-off. If you wish accurate timing,
  897.           you pay for it in much-increased code-size.
  898.  
  899.           Modems:
  900.  
  901.           When JMODEM gets control, it turns ON CTS and DSR just in
  902.           case the BBS program has turned them off (WILDCAT does).
  903.           Some modems "hiccup" when this occurs, and the RTS line will
  904.           bounce. This caused JMODEM to "wait forever" for a RTS that
  905.           never occurs. Therefore I added a 1/2 second delay between
  906.           the time that I first set these bits and the time I start
  907.           checking for RTS and RLSD for flow-control and a possible
  908.           abort. This fixed this problem. The flow-control problem is
  909.           complex because user's might wish to transfer files between
  910.           two computers using only three wires. In such a case, there
  911.           is no flow-control and there is no modem carrier. To accom-
  912.           modate a universal solution to various hookups, JMODEM
  913.           checks for the state of DSR/CTS and RLSD when it first gets
  914.           control. If there is no carrier at this time, JMODEM will
  915.           not check for an aborted carrier during transmission or
  916.           reception. If JMODEM detects a CHANGE in either DSR or CTS,
  917.           it assumes this is flow-control and waits for these bits to
  918.           change back to whatever they were when JMODEM first obtained
  919.           control. This protocol has been used successfully since the
  920.           very first version of JMODEM. There is, however, a pos-
  921.           sibility of JMODEM wrongly interpreting what it finds if
  922.           there is "bounce" when it first gets control. That's the
  923.           reason for the delay. In any event, the normal "timeout"
  924.           trap will prevent a hung system.
  925.  
  926.           BBS systems:
  927.  
  928.           JMODEM still gets blamed for crashing some BBS systems even
  929.           though it is not JMODEM's fault. A common problem occurs
  930.           with systems that use compiled BASIC. Some BBS system pro-
  931.           grams assume certain characteristics about external proto-
  932.           cols and will blow up when the assumption is wrong. If you
  933.           use BASIC code that works like this:
  934.  
  935.                 PROTOSEND$ = "JMODEM S1 "
  936.                 COMSTRING$ = PROTOSEND$+FILENAME$
  937.  
  938.                 SHELL COMSTRING$
  939.  
  940.  
  941.  
  942.  
  943.  
  944.                                      - 16 -
  945.                                                JMODEM, the C Version
  946.  
  947.  
  948.                 ... Then JMODEM (and other protocols) will work okay.
  949.  
  950.           However, If you attempt to BLOAD, CALL, or CHAIN to it, the
  951.           results will be indeterminate. This is because JMODEM
  952.           allocates memory from C runtime routines that get their
  953.           memory from DOS (not BASIC). BASIC will not "know" that its
  954.           memory has been used by the external protocol. If you exe-
  955.           cute the "SHELL" command, then you force BASIC to give up
  956.           all the memory that it can afford to spare. This free memory
  957.           is recorded by DOS and can be used for the external proto-
  958.           col.
  959.  
  960.           BBS systems written is C should execute external protocols
  961.           something like this:
  962.  
  963.                 strcpy(command_line,"JMODEM S1 FILENAME");
  964.                 system (command_line);
  965.  
  966.           The C "system" command executes DOS commands from within C
  967.           programs by freeing memory and then executing COMMAND.COM.
  968.           Some C compilers don't have to load an aditional copy of
  969.           COMMAND.COM. They use an undocumented "back-door" to the
  970.           existing command interpreter! This saves memory.
  971.  
  972.           This is a sneak preview of the undocumented procedure:
  973.  
  974.           MOV   WORD PTR [SP_SAV],SP    ; Put the SP in a safe place
  975.           MOV   WORD PTR [SS_SAV],SS    ; Save segment registers.
  976.           MOV   WORD PTR [DS_SAV],DS
  977.           MOV   WORD PTR [ES_SAV],ES
  978.           MOV   AX,4A00H                ; Free memory
  979.           MOV   BX,OFFSET TOP           ; Point to the top of code
  980.           MOV   CL,4                    ; Bits to shift
  981.           SHR   BX,CL                   ; Div / 16
  982.           INC   BX                      ; Round up
  983.           INT   21H                     ; Free some memory
  984.           ;
  985.           MOV   SI,OFFSET COMMAND       ; Point to the command
  986.           INT   2EH                     ; Make the undocumented call
  987.           CLI                           ; No interrupts, cleaning up
  988.           MOV   DS,WORD PTR CS:[DS_SAV] ; Restore all segments
  989.           MOV   ES,WORD PTR [DS_SAV]
  990.           MOV   SS,WORD PTR [SS_SAV]
  991.           MOV   SP,WORD PTR [SP_SAV]    ; Restore stack pointer
  992.           STI                           ; Allow interrupts
  993.  
  994.           If JMODEM and other external protocols are executed from BBS
  995.           software in this manner, then you will have no problems.
  996.           JMODEM preserves the BBS system communications environment
  997.           so BBS systems don't have to reinitialize anything when they
  998.           get control. JMODEM does not even touch the baud rate! Its
  999.  
  1000.  
  1001.  
  1002.  
  1003.                                      - 17 -
  1004.                                                JMODEM, the C Version
  1005.  
  1006.  
  1007.           not necessary to alter any communications parameters so it
  1008.           doesn't.
  1009.  
  1010.           A small program, SHOW.C is provided with this distribution.
  1011.           It is a C program that allocates a lot of memory, writes to
  1012.           the memory, then executes JMODEM.EXE using the "system"
  1013.           command. After JMODEM returns from the shell, SHOW then
  1014.           continues to write to memory before exiting. Since this
  1015.           procedure is properly written, no system crash will occur.
  1016.           You can load multiple copies of COMMAND.COM to "eat" memory.
  1017.           Eventually there will be too little memory available for
  1018.           JMODEM to execute. The system will still not crash.
  1019.  
  1020.           Help:
  1021.  
  1022.           JMODEM is now over three years old. I first wrote it in
  1023.           assembly and slowly it caught on. I spent last Christmas
  1024.           writing it in C. Since the C release, I have received over
  1025.           500 comments from persons telling me how to make it better.
  1026.           Most of these comments were from so-called professional
  1027.           programmers who complained about various things. Others
  1028.           complained about the comments I made about them in this
  1029.           document <grin>.
  1030.  
  1031.           Please remember that an enhancement is not a "preference".
  1032.           If you prefer to do something one way or another then feel
  1033.           free to modify the code for your own use. If you find a
  1034.           better way to do something then please let me know.
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.                                      - 18 -
  1063.                                                JMODEM, the C Version
  1064.  
  1065.  
  1066.                             JMODEM revision history
  1067.  
  1068.           The revision history has been moved to JMODEM_A.C and to
  1069.           JMODEM.H (identical copies). This makes it easier to keep
  1070.           the documentation current.
  1071.  
  1072.           Version V3.08 does not do anything except make the code
  1073.           comply with Microsoft's interpretation of the ANSI standard
  1074.           so it will compile at their new "warning-level /W4" without
  1075.           any warning errors. Jeff Jevnisek warned me about the new
  1076.           C600 compiler and I had to go out and buy it. He also mod-
  1077.           ified the code to be "Microsoft compliant" so, as usual,
  1078.           there are no warning errors when compiling.
  1079.  
  1080.           Microsoft, supplying over 80 percent of the 'C' compilers in
  1081.           use for the PC environment, is a force that must be accom-
  1082.           modated even though they are < W R O N G >, damned wrong!
  1083.           Here's an example of what they now REQUIRE to pass their
  1084.           "warning-level 4" test:
  1085.  
  1086.           Given this CORRECT code....
  1087.  
  1088.           short function (param)
  1089.           short param;
  1090.           {
  1091.               return param;
  1092.           }
  1093.  
  1094.           ... we now need this:
  1095.  
  1096.           short function (short param)
  1097.           {
  1098.               return param;
  1099.           }
  1100.  
  1101.           ANSI allowed (read ALLOWED) the inclusion of the object size
  1102.           (type) within the parameter list to facilitate making the
  1103.           parser for the compiler. With the "old-style" method, the
  1104.           size of the object was not known until the next line was
  1105.           read so the compiler had to store the previous variable
  1106.           names (such a pity) until it got to the line that represent-
  1107.           ed the size and type of the object. Microsoft was one of the
  1108.           ANSI committee representatives that insisted upon the allow-
  1109.           ance for including this information within the parameter
  1110.           list. It was ALLOWED by the committee. Now anything not in
  1111.           conformance with Microsoft's WISH is flagged as an error!
  1112.  
  1113.           The second problem is that the NULL object (not anything
  1114.           having to do with ANSI) was previously a generic VALUE of
  1115.           zero that could be assigned to any size object including
  1116.           pointers of all types, ASCII string terminators, etc. This
  1117.  
  1118.  
  1119.  
  1120.  
  1121.                                      - 19 -
  1122.                                                JMODEM, the C Version
  1123.  
  1124.  
  1125.           is no longer the case. One must cast it to the appropriate
  1126.           type before use!! I got rid of all references to NULL
  1127.           because it no longer has the required special character-
  1128.           istics.
  1129.  
  1130.           - finis -
  1131.  
  1132.  
  1133.  
  1134.  
  1135.  
  1136.  
  1137.  
  1138.  
  1139.  
  1140.  
  1141.  
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.                                      - 20 -
  1181.